package com.qcq.wecheck.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.qcq.wecheck.dto.AttendanceCountDto;
import com.qcq.wecheck.dto.ComboDto;
import com.qcq.wecheck.entity.Attendance;
import com.qcq.wecheck.entity.Schedule;
import com.qcq.wecheck.mapper.AttendanceMapper;
import com.qcq.wecheck.service.AttendanceService;
import com.qcq.wecheck.util.PredicateUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

/**
 * <p>
 * 签到记录表 服务实现类
 * </p>
 *
 * @author O
 * @since 2018-09-19
 */
@Service
public class AttendanceServiceImpl extends ServiceImpl<AttendanceMapper, Attendance> implements AttendanceService {
	@Resource
	private AttendanceMapper attendanceMapper;

	/**
	 * 获取vo之后还要补齐没有的日期
	 */
	@Override
	public List<AttendanceCountDto> getAttendanceCount(String openId, Long scheduleId, String from, String to) {
		List<AttendanceCountDto> vos = attendanceMapper.getAttendanceCountByDates(openId, scheduleId, from, to);

		int count = (int) ChronoUnit.DAYS.between(
				LocalDate.parse(from, DateTimeFormatter.ISO_DATE),
				LocalDate.parse(to, DateTimeFormatter.ISO_DATE))
				+ 1;
		List<AttendanceCountDto> emptyDays = Stream
				.iterate(LocalDate.parse(from, DateTimeFormatter.ISO_DATE), date -> date.plusDays(1))
				.limit(count)
				.map(date -> {
					if (vos.stream().noneMatch(vo -> vo.getDate().isEqual(date))) {
						AttendanceCountDto vo = new AttendanceCountDto();
						return vo.setCount(0L).setDate(date);
					}
					return null;
				})
				.filter(PredicateUtils::isNotNullAttendanceCountVo)
				.collect(toList());
		vos.addAll(emptyDays);
		vos.sort(Comparator.comparing(AttendanceCountDto::getDate));
		return vos;
	}

	@Override
	public List<Attendance> getByDate(String openId, Long scheduleId, String date) {
		return attendanceMapper.getByDate(openId, scheduleId, date);
	}

	@Override
	public ComboDto getCombo(Schedule schedule, String openId) {
		ComboDto combo = new ComboDto();
		int requiredCount = schedule.getCheckCount();
		//最新日期
		LocalDate latestDate = schedule.getEndDate().isBefore(LocalDate.now()) ?
				schedule.getEndDate() : LocalDate.now();


		List<AttendanceCountDto> countDtos = this.getAttendanceCount(openId,
				schedule.getId(),
				schedule.getStartDate().format(DateTimeFormatter.ISO_DATE),
				latestDate.format(DateTimeFormatter.ISO_DATE));
		int fullCount = (int) countDtos.stream()
				.filter(dto -> PredicateUtils.isFinishedAttendanceCountVo(dto, requiredCount))
				.count();
		int legalCount = (int) countDtos.stream()
				.filter(PredicateUtils::isLegalDateAttendanceCountVo)
				.count();
		int unFullCount = (int) countDtos.stream()
				.filter(dto -> PredicateUtils.isUnFinishedAttendanceCountVo(dto, requiredCount))
				.count();

		combo.setFullCount(fullCount);
		combo.setUnFullCount(unFullCount);
		combo.setAbsentCount(legalCount - fullCount - unFullCount);
		return combo;
	}

	@Override
	public Integer deleteHistory(Long scheduleId, String openId) {
		return attendanceMapper.deleteHistory(scheduleId, openId);
	}

	@Override
	public Long getAttendanceCount(String openId, Long scheduleId, LocalDate date) {
		return getAttendances(openId, scheduleId)
				.stream()
				.filter(a -> a.getCheckTime().toLocalDate().isEqual(date))
				.count();
	}

	@Override
	public List<Attendance> getAttendances(String openId, Long scheduleId) {
		EntityWrapper<Attendance> wrapper = new EntityWrapper<>();
		wrapper.eq("open_id", openId)
				.eq("schedule_id", scheduleId);
		return attendanceMapper.selectList(wrapper);
	}
}
